﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace LibrarySystem
{
  public partial class ImageCode : System.Web.UI.Page
  {
    protected void Page_Load(object sender, EventArgs e)
    {
      string tmp = RndNum(4);                   // 随机产生4位数字的字符串，即验证码图片中的4个字符，RndNum()方法在下面定义
      HttpCookie iamageV = new HttpCookie("ImageV", tmp);
      Response.Cookies.Add(iamageV);
      this.ValidateCode(tmp);
    }

    private void ValidateCode(string VNum)
    {
      Bitmap Img = null;                        // 定义位图对象
      Graphics g = null;                        // 定义图形对象
      MemoryStream ms = null;                   // 定义内存流对象
      int gwidth = VNum.Length * 12;            // 图形宽度
      Img = new Bitmap(gwidth, 25);             // 给定图形的宽度和高度实例化位图对象
      g = Graphics.FromImage(Img);              // 实例化图形对象

      Random random = new Random();             // 实例化随机生成器对象

      g.Clear(Color.White);                     // 用白色填充整个图形
                                                // 在图形中随机画100个噪点
      for (int i = 0; i < 100; i++)
      {
        int x = random.Next(Img.Width);         // 在位图的大小范围内随机生成横坐标x
        int y = random.Next(Img.Height);        // 在位图的大小范围内随机生成纵坐标y
        Img.SetPixel(x, y, Color.FromArgb(random.Next()));  // 用随机颜色在位图的(x,y)位置画点
      }

      Font f = new Font("Arial Black ", 12);    // 文字字体
      SolidBrush s = new SolidBrush(Color.Red); // 画笔颜色
      g.DrawString(VNum, f, s, 3, 3);           // 将保存在VNum中的随机产生的4位数字字符串画在图形中       
      ms = new MemoryStream();                  // 实例化内存流对象
      Img.Save(ms, ImageFormat.Jpeg);           // 将图形以Jpeg的格式保存到内存流         
      Response.ClearContent();                  // 清除缓冲区流中的所有内容
      Response.ContentType = "image/Jpeg ";     // 指定输出流内容的类型为image/Jpeg
      Response.BinaryWrite(ms.ToArray());       // 将内存流的图形输出到网页
      g.Dispose();                              // 释放图形对象
      Img.Dispose();                            // 释放位图对象
      Response.End();                           // 将当前所有缓冲的输出发送到客户端，停止程序执行
    }

    // 随机产生VcodeNum位数字的字符串
    private string RndNum(int VcodeNum)
    {
      string Vchar = "0,1,2,3,4,5,6,7,8,9";
      string[] VcArray = Vchar.Split(new Char[] { ',' }); // 实例化数组对象VcArray，该数组元素的值分别为'0'-'9'
      string VNum = "";
      int temp = -1;
      Random rand = new Random();                // 实例化随机生成器对象
      for (int i = 1; i < VcodeNum + 1; i++)     // 进行VcodeNum次循环，每次循环随机产生一个数
      {
        // 实际上这段程序没有必要，Random()方法本身就使用与时间相关的默认种子，将这段程序注释掉，从运行结果看并没有影响该方法生成的数的随机性
        if (temp != -1)                          // 如果不是第一次循环
        {
          rand = new Random(i * temp * unchecked((int)DateTime.Now.Ticks));  // ，则重新实例化随机生成器对象，unchecked()取消类型转换时数值溢出检查
        }

        int t = rand.Next(10);                    // 随机生成一个0-9范围内的整数

        // 实际上这段程序没有必要，即使相邻的两个相同也没关系
        if (temp != -1 && temp == t)             // 如果生成的随机数与上次相同，
        {
          return RndNum(VcodeNum);               // 则调用RndNum()重新生成
        }

        temp = t;
        VNum += VcArray[t];
      }
      return VNum;
    }
  }
}